#include <list>


#define CREATE_TYPE_print(z, n, data) \
	BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(data,n).derived()

#define PUSH_TYPE_print(z, n, data) \
	data.push_back(\
		param_generator<BOOST_PP_CAT(T,BOOST_PP_ADD(n,1)),\
						InfoT,\
						typename BOOST_PP_CAT(T,BOOST_PP_ADD(n,1))::generator_category_t\
					   >::get_parameter(this->BOOST_PP_CAT(subj,BOOST_PP_ADD(n,1)),info)\
	);

#define POP_TYPE_print(z, n, data) \
	param_generator<BOOST_PP_CAT(T,BOOST_PP_ADD(n,1)),\
					InfoT,\
					typename BOOST_PP_CAT(T,BOOST_PP_ADD(n,1))::generator_category_t\
				   >::delete_parameter(data.front());\
	data.pop_front();

namespace gen {

	#define GEN_VA_ARG_IMPL_size(z, n, unused)										\
		template < BOOST_PP_ENUM_PARAMS(n, class T) >								\
		template <typename InfoT>													\
		void																		\
		BOOST_PP_CAT(va_arg,n)<BOOST_PP_ENUM_PARAMS(n,T)>::generate(InfoT & info) const\
		{																			\
			std::list<boost::any> args;												\
			BOOST_PP_REPEAT(BOOST_PP_SUB(n,1), PUSH_TYPE_print, args)				\
			info.push(args.begin(), args.end());									\
			subj0.generate(info);													\
			info.pop();																\
			BOOST_PP_REPEAT(BOOST_PP_SUB(n,1), POP_TYPE_print, args)				\
		}																			\
																					\
		template <typename DerivedT>												\
		template <BOOST_PP_ENUM_PARAMS( BOOST_PP_SUB(n,1), class T)>				\
		BOOST_PP_CAT(va_arg,n)< DerivedT, BOOST_PP_ENUM_PARAMS( BOOST_PP_SUB(n,1), T) >	\
		generator<DerivedT>::operator()( BOOST_PP_REPEAT(BOOST_PP_SUB(n,1), GENERATOR_TYPE_print, g) ) const		\
		{																						\
			return BOOST_PP_CAT(va_arg,n)<DerivedT, BOOST_PP_ENUM_PARAMS(BOOST_PP_SUB(n,1),T)>	\
									(derived(),BOOST_PP_REPEAT(BOOST_PP_SUB(n,1), CREATE_TYPE_print, g));			\
		}	

	#include <boost/preprocessor/iteration/local.hpp>

	#define BOOST_PP_LOCAL_MACRO(n)   GEN_VA_ARG_IMPL_size(~, n, ~)
	#define BOOST_PP_LOCAL_LIMITS     (2, GEN_VA_ARG_SIZE - 1)
	#include BOOST_PP_LOCAL_ITERATE()

}


#undef CREATE_TYPE_print
#undef PUSH_TYPE_print
#undef POP_TYPE_print
